import os
import argparse
import logging
from runconfig import RunConfig
from hdc import Hdc
from scenario import Scenario
from action import Action
from stresslogger import MyStressLogger

logging.basicConfig(
    level = logging.DEBUG,
    format = "%(asctime)s - %(levelname)s - %(message)s"
)

def main() -> int:
    parser = argparse.ArgumentParser(description='[ByteFun-AutotestScript] run test suite')
    parser.add_argument('-p', '--hdcpath', help='hdc path', default="hdc")
    parser.add_argument('-d', '--device', help='device serial', default="")
    parser.add_argument('-c', '--config', help='run config file path', required=True)
    args = parser.parse_args()

    hdc_path = args.hdcpath.strip()
    device_id = args.device.strip()
    run_cfg_path = args.config.strip()

    # check hdc path
    if hdc_path != "" and os.path.exists(hdc_path):
        logging.error(f"HDC executable file not found at '{hdc_path}'")
        return -1
    
    hdc: Hdc = Hdc(hdc_path)

    # check devices
    targets = hdc.targets()
    if len(targets) == 0:
        logging.error("No device found")
        return -1
    if device_id != "" and device_id not in [target["device_id"] for target in targets]:
        logging.error(f"Device '{device_id}' not found")
        return -1

    # init run config
    run_config = RunConfig(run_cfg_path)
    logging.info(f"\n{run_config.to_string()}\n")
    
    # test log monitor start
    # app = "com.ss.hm.article.news" # input bundle name of test app
    app = "com.ss.hm.ugc.aweme"
    pid = hdc.pidof(device_id, app)
    stress_log = MyStressLogger()
    stress_log.set_property("hdc", hdc)
    stress_log.set_property("device_id", device_id)
    stress_log.set_property("bundle_name", app)
    stress_log.set_property("pid", pid)
    stress_log.start()

    # scenario callbacks 
    def scenario_before(scenario: any):
        scenario_inst: Scenario = scenario
        logging.info(f"before scenario iteration: {scenario_inst.name}")

    def scenario_after(entity: any):
        scenario_inst: Scenario = scenario
        logging.info(f"after scenario iteration: {scenario_inst.name}")

    def iteration_before(scenario: any, iteration: any):
        scenario_inst: Scenario = scenario
        iteration_inst: list = iteration
        logging.info(f"before scenario: {scenario_inst.name}, iteration action count: {len(iteration_inst)}")

    def iteration_after(scenario: any, iteration: any):
        scenario_inst: Scenario = scenario
        iteration_inst: list = iteration
        logging.info(f"after scenario: {scenario_inst.name}, iteration action count: {len(iteration_inst)}")
        
        # process stress log after every iteration
        stress_log.process()
        
        # memory info
        logging.info(hdc.mem_info(device_id, pid))
        
    def action_before(scenario: any, iteration: any, action: any):
        scenario_inst: Scenario = scenario
        iteration_inst: list = iteration
        action_inst: Action = action
        logging.info(f"before scenario: {scenario_inst.name}, iteration action count: {len(iteration_inst)}, action: {action_inst.name}")
        
    def action_after(scenario: any, iteration: any, action: any):
        scenario_inst: Scenario = scenario
        iteration_inst: list = iteration
        action_inst: Action = action
        logging.info(f"after scenario: {scenario_inst.name}, iteration action count: {len(iteration_inst)}, action: {action_inst.name}")
        
        # scenario stop
        if scenario_inst.stopped:
            scenario_inst.stop()

    # register callbacks
    for scenario in run_config.scenarios:
        scenario.reg_scenario_start_callback(scenario_before)
        scenario.reg_scenario_stop_callback(scenario_after)
        scenario.reg_scenario_iteration_start_callback(iteration_before)
        scenario.reg_scenario_iteration_stop_callback(iteration_after)
        scenario.reg_scenario_iteration_action_start_callback(action_before)
        scenario.reg_scenario_iteration_action_stop_callback(action_after)

    # execute scenarios test
    for scenario in run_config.scenarios:
        scenario.execute(hdc, device_id)

    # unregister callbacks
    for scenario in run_config.scenarios:
        scenario.unreg_scenario_start_callbacks()
        scenario.unreg_scenario_stop_callbacks()
        scenario.unreg_scenario_iteration_start_callbacks()
        scenario.unreg_scenario_iteration_stop_callbacks()
        scenario.unreg_scenario_iteration_action_start_callbacks()
        scenario.unreg_scenario_iteration_action_stop_callbacks()

    # test report

    # test end

if __name__ == "__main__":
    main()